home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume18 / pwdiff < prev    next >
Encoding:
Internet Message Format  |  1989-03-26  |  8.0 KB

  1. Subject:  v18i068:  Tool to aide in merging password files
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Don Libes <libes@cme-durer.arpa>
  7. Posting-number: Volume 18, Issue 68
  8. Archive-name: pwdiff
  9.  
  10. pwdiff takes multiple password files and compares them in an
  11. intelligent way.  For instance, it will report on different names
  12. with the same uid, but let pass the same name with the same uid.
  13.  
  14. What happened was that we started out with one shared password file in
  15. a small LAN environment.  Over time, more machines came on-line.
  16. New administrators sometimes shared the old password file, and
  17. sometimes just copied it.  Gradually it diverged, so that some of the
  18. uids mapped to multiple users across the LAN.
  19.  
  20. Eventually our LAN got big enough, so that we hired a sitewide admin,
  21. and he wanted to use one common password file.  This makes NFS access
  22. much easier, for example.  So I wrote this program to solve his
  23. problem.  I figure this very same thing must happen to lots of sites,
  24. so to save you some grief, here it is.
  25.         Don Libes
  26.  
  27. #! /bin/sh
  28. # This is a shell archive.  Remove anything before this line, then unpack
  29. # it by saving it into a file and typing "sh file".  To overwrite existing
  30. # files, type "sh file -c".  You can also feed this as standard input via
  31. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  32. # will see the following message at the end:
  33. #        "End of shell archive."
  34. # Contents:  Makefile README pwdiff.8 pwdiff.c
  35. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  36. echo Extracting Makefile \(entered by hand, no error checking\)
  37. sed "s/^X//" >Makefile <<'END_OF_FILE'
  38. Xall:        pwdiff pwdiff.8
  39. X
  40. Xinstall:    all
  41. X    @echo Installing according to local convention
  42. X
  43. Xpwdiff:        pwdiff.c
  44. X    $(CC) -o pwdiff $(CFLAGS) pwdiff.c
  45. END_OF_FILE
  46. if test -f 'README' -a "${1}" != "-c" ; then 
  47.   echo shar: Will not clobber existing file \"'README'\"
  48. else
  49. echo shar: Extracting \"'README'\" \(1089 characters\)
  50. sed "s/^X//" >'README' <<'END_OF_FILE'
  51. Xpwdiff takes multiple password files and compares them in an
  52. Xintelligent way.  For instance, it will report on different names
  53. Xwith the same uid, but let pass the same name with the same uid.
  54. X
  55. XI wrote it one day when we had to join two password files from
  56. Xdifferent machines.
  57. X
  58. XWhat happened was that we started out with one shared password file in
  59. Xa small LAN environment.  Over time, more machines came on-line.
  60. XNew administrators sometimes shared the old password file, and
  61. Xsometimes just copied it.  Gradually it diverged, so that some of the
  62. Xuids mapped to multiple users across the LAN.
  63. X
  64. XEventually our LAN got big enough, so that we hired a sitewide admin,
  65. Xand he wanted to use one common password file.  This makes NFS access
  66. Xmuch easier, for example.  So I wrote this program to solve his
  67. Xproblem.  I figure this very same thing must happen to lots of sites,
  68. Xso to save you some grief, here it is.  Send bugs, improvements, and
  69. Xcash to me.
  70. X
  71. XDon Libes
  72. XNational Bureau of Standards
  73. XBldg 220, Rm A-127
  74. XGaithersburg, MD  20899
  75. X(301) 975-3535
  76. Xlibes@cme-durer.arpa
  77. Xuunet!cme-durer!libes
  78. END_OF_FILE
  79. if test 1089 -ne `wc -c <'README'`; then
  80.     echo shar: \"'README'\" unpacked with wrong size!
  81. fi
  82. # end of 'README'
  83. fi
  84. if test -f 'pwdiff.8' -a "${1}" != "-c" ; then 
  85.   echo shar: Will not clobber existing file \"'pwdiff.8'\"
  86. else
  87. echo shar: Extracting \"'pwdiff.8'\" \(724 characters\)
  88. sed "s/^X//" >'pwdiff.8' <<'END_OF_FILE'
  89. X.TH PWDIFF 8 "25 June 1988"
  90. X.SH NAME
  91. Xpwdiff \- find differences in password files
  92. X.SH SYNOPSIS
  93. Xpwdiff file1 file2 file3 ...
  94. X.SH DESCRIPTION
  95. XThis program compares multiple password files and reports on uid or
  96. Xname conflicts that would prevent the files from being merged.
  97. X.PP
  98. XFor example, if uid 27 is don in file1 and susan in file2, this will be
  99. Xdetected.
  100. X.PP
  101. XThe program also notes syntactically incorrect lines and nicknames
  102. X(the user name does not match the home directory).  Since many low
  103. Xuids are nicknames (root, uucp, etc.) a compile-time constant controls
  104. Xa cut-off below which nicknames are ignored.  As distributed, uids
  105. Xbelow 20 are not checked for nicknames.
  106. X.SH AUTHOR
  107. XDon Libes, National Bureau of Standards
  108. END_OF_FILE
  109. if test 724 -ne `wc -c <'pwdiff.8'`; then
  110.     echo shar: \"'pwdiff.8'\" unpacked with wrong size!
  111. fi
  112. # end of 'pwdiff.8'
  113. fi
  114. if test -f 'pwdiff.c' -a "${1}" != "-c" ; then 
  115.   echo shar: Will not clobber existing file \"'pwdiff.c'\"
  116. else
  117. echo shar: Extracting \"'pwdiff.c'\" \(3311 characters\)
  118. sed "s/^X//" >'pwdiff.c' <<'END_OF_FILE'
  119. X/* Check multiple passwd files for uid/name overlap - Don Libes */
  120. X
  121. X#include <stdio.h>
  122. X#include <pwd.h>
  123. X
  124. X#define TRUE 1
  125. X#define FALSE 0
  126. X
  127. Xstruct tinypasswd {    /* like struct pwd but missing some entries */
  128. X    char *name;
  129. X    char *dir;
  130. X    struct tinypasswd *next;  /* other entries mapping to same uid */
  131. X    char *file;          /* file this entry was found in */
  132. X};
  133. X
  134. X#define MINUSERUID    20    /* don't check uids below this for */
  135. X                /* names to match directories */
  136. X#define MAXLINELEN    132
  137. X#define MAXUID        5700        /* largest uid we might possibly see */
  138. X#define NOBODY        -2
  139. X#define skipuid(x)    (x == NOBODY)    /* any uids to skip.  If none */
  140. X                    /* then just define to be 0 */
  141. X
  142. Xstruct tinypasswd *pwds[MAXUID];
  143. Xchar line[MAXLINELEN];
  144. Xstruct tinypasswd *pwd;
  145. X
  146. Xchar *malloc();
  147. Xchar *newstr();
  148. Xchar *rindex();
  149. Xstruct passwd *fgetpwent();
  150. X#define new(type)    (type *)malloc(sizeof(type))
  151. X
  152. Xmain(argc,argv)
  153. Xint argc;
  154. Xchar **argv;
  155. X{
  156. X    int file;
  157. X    int uid;
  158. X    FILE *pfp;
  159. X    struct passwd *staticpwd;
  160. X    char *leaf;
  161. X
  162. X    for (uid=0;uid<MAXUID;uid++) pwds[uid] = NULL;
  163. X
  164. X    for (file=1;file<argc;file++) {
  165. X        if (NULL == (pfp = fopen(argv[file],"r"))) {
  166. X            perror(argv[file]);
  167. X            continue;
  168. X        }
  169. X
  170. X        while (NULL != (staticpwd = fgetpwent(pfp))) {
  171. X            if (pwd == NULL) {
  172. X                if (NULL == (pwd = new(struct tinypasswd))) {
  173. X                    printf("malloc: out of space\n");
  174. X                    exit(-1);
  175. X                }
  176. X            }
  177. X
  178. X            /* skip Sun yp hook */
  179. X            if (staticpwd->pw_name[0] == '+') continue;
  180. X
  181. X            pwd->name = newstr(staticpwd->pw_name);
  182. X            pwd->dir = newstr(staticpwd->pw_dir);
  183. X            uid = staticpwd->pw_uid;
  184. X
  185. X            if (skipuid(uid)) continue;
  186. X            if (uid < 0 || uid >= MAXUID) {
  187. X                printf("%s: uid %d out of range\n",
  188. X                    argv[file],uid);
  189. X                continue;
  190. X            }
  191. X
  192. X            /* check for matching directories on large uids */
  193. X            if (uid > MINUSERUID) {
  194. X                if (0 == (leaf = rindex(pwd->dir,'/'))) {
  195. X                    printf("%s: no leaf in directory %s\n",
  196. X                        argv[file],line);
  197. X                } else if (0 != strcmp(pwd->name,1+leaf)) {
  198. X                    printf("%s: nickname %s has directory %s\n",
  199. X                        argv[file],pwd->name,pwd->dir);
  200. X                }
  201. X            }
  202. X
  203. X            pwd->file = argv[file];
  204. X            pwd->next = NULL;
  205. X
  206. X            if (!hash_pwd(&pwds[uid],pwd)) {
  207. X                free(pwd->name);
  208. X                free(pwd->dir);
  209. X            } else pwd = NULL;
  210. X        }
  211. X        fclose(pfp);
  212. X    }
  213. X
  214. X    /* scan down list looking for dups */
  215. X    for (uid=0;uid<MAXUID;uid++) {
  216. X        /* no pwd with this uid */
  217. X        if (pwds[uid] == NULL) continue;
  218. X
  219. X        /* no other pwd with this uid */
  220. X        if (pwds[uid]->next == NULL) continue;
  221. X
  222. X        print_pwd(uid);
  223. X    }
  224. X}
  225. X
  226. Xprint_pwd(uid)
  227. Xint uid;
  228. X{
  229. X    struct tinypasswd *p;
  230. X
  231. X    for (p = pwds[uid];p;p=p->next) {
  232. X        printf("%6d %20s %40s\n",uid,p->name,p->file);
  233. X    }
  234. X}
  235. X
  236. X/* returns TRUE if pwd stored, FALSE if not stored */
  237. Xhash_pwd(pep,p)
  238. Xstruct tinypasswd **pep;    /* pwds entry pointer */
  239. Xstruct tinypasswd *p;
  240. X{
  241. X    int different = FALSE;
  242. X    struct tinypasswd *pptr;  /* pointer to open-hashed pwd entries */
  243. X    struct tinypasswd *lastp; /* where to append new struct passwd */
  244. X
  245. X    if (NULL == *pep) {
  246. X        *pep = p;
  247. X        return(TRUE);
  248. X    }
  249. X
  250. X    for (pptr = *pep;pptr;pptr=pptr->next) {
  251. X        lastp = pptr;
  252. X        if (different) continue;    /* just get to end of list */
  253. X        if (0 != strcmp(pptr->name,p->name)) different = TRUE;
  254. X    }
  255. X    if (different) lastp->next = p;
  256. X
  257. X    return(different);
  258. X}
  259. X
  260. Xchar *newstr(s)
  261. Xchar *s;
  262. X{
  263. X    char *news;
  264. X
  265. X    if (!(news = malloc(1+strlen(s)))) {
  266. X        printf("newstr: out of space\n");
  267. X        exit(0);
  268. X    }
  269. X    strcpy(news,s);
  270. X    return(news);
  271. X}
  272. END_OF_FILE
  273. if test 3311 -ne `wc -c <'pwdiff.c'`; then
  274.     echo shar: \"'pwdiff.c'\" unpacked with wrong size!
  275. fi
  276. # end of 'pwdiff.c'
  277. fi
  278. echo shar: End of shell archive.
  279. exit 0
  280.  
  281.